import streamlit as st
from typing import Dict, Any
from ..utils.config_manager import config_manager

def render_config_page():
    """渲染配置页面"""
    
    st.header("⚙️ 处理配置")
    st.markdown("配置数据清洗和文档切片参数")
    
    # 初始化配置（如果session_state为空，从文件加载）
    initialize_config_from_file()
    
    # 创建两列布局
    col1, col2 = st.columns(2)
    
    with col1:
        render_cleaning_config()
    
    with col2:
        render_chunking_config()
    
    # 配置操作按钮
    st.markdown("---")
    render_config_actions()
    
    # 预设配置
    st.markdown("---")
    render_preset_configs()
    
    # 配置预览
    st.markdown("---")
    render_config_preview()

def render_cleaning_config():
    """渲染数据清洗配置"""
    
    st.subheader("🧹 数据清洗配置")
    
    # 基础清洗选项
    st.markdown("**基础清洗**")
    
    clean_unicode = st.checkbox(
        "Unicode规范化",
        value=st.session_state.get('clean_unicode', True),
        help="将Unicode字符规范化为标准形式"
    )
    
    remove_special_chars = st.checkbox(
        "移除特殊字符",
        value=st.session_state.get('remove_special_chars', True),
        help="移除不可见字符和控制字符"
    )
    
    fix_line_breaks = st.checkbox(
        "修复断行",
        value=st.session_state.get('fix_line_breaks', True),
        help="修复PDF等格式中的不当断行"
    )
    
    # 内容清洗选项
    st.markdown("**内容清洗**")
    
    remove_headers_footers = st.checkbox(
        "移除页眉页脚",
        value=st.session_state.get('remove_headers_footers', False),
        help="尝试识别并移除重复的页眉页脚内容"
    )
    
    remove_duplicates = st.checkbox(
        "去除重复内容",
        value=st.session_state.get('remove_duplicates', True),
        help="移除重复的段落和句子"
    )
    
    remove_empty_lines = st.checkbox(
        "移除空行",
        value=st.session_state.get('remove_empty_lines', True),
        help="移除多余的空行，保持文档整洁"
    )
    
    # 高级清洗选项
    st.markdown("**高级选项**")
    
    min_line_length = st.slider(
        "最小行长度",
        min_value=0,
        max_value=50,
        value=st.session_state.get('min_line_length', 3),
        help="移除少于指定字符数的行"
    )
    
    preserve_formatting = st.checkbox(
        "保留格式标记",
        value=st.session_state.get('preserve_formatting', False),
        help="保留Markdown等格式的标记符号"
    )
    
    # 更新session state
    st.session_state.update({
        'clean_unicode': clean_unicode,
        'remove_special_chars': remove_special_chars,
        'fix_line_breaks': fix_line_breaks,
        'remove_headers_footers': remove_headers_footers,
        'remove_duplicates': remove_duplicates,
        'remove_empty_lines': remove_empty_lines,
        'min_line_length': min_line_length,
        'preserve_formatting': preserve_formatting
    })

def render_chunking_config():
    """渲染文档切片配置"""
    
    st.subheader("✂️ 文档切片配置")
    
    # 获取当前策略索引
    current_strategy = st.session_state.get('chunking_strategy', 'fixed_length')
    strategy_options = ["fixed_length", "content_type", "document_structure", "hierarchical", "custom_delimiter", "question_based"]
    
    try:
        current_index = strategy_options.index(current_strategy)
    except ValueError:
        current_index = 0
    
    # 切片策略选择
    chunking_strategy = st.selectbox(
        "切片策略",
        options=strategy_options,
        format_func=lambda x: {
            "fixed_length": "固定长度切片",
            "content_type": "按内容类型切片",
            "document_structure": "按文档结构切片",
            "hierarchical": "层级结构切片",
            "custom_delimiter": "自定义分隔符切片",
            "question_based": "题目结构切片"
        }[x],
        index=current_index,
        key="chunking_strategy_selector"
    )
    
    # 保存选择的切片策略到session_state
    if 'chunking_config' not in st.session_state:
        st.session_state['chunking_config'] = {}
    
    # 将英文策略名称映射为中文策略名称（与切片引擎保持一致）
    strategy_mapping = {
        "fixed_length": "固定长度分段",
        "content_type": "按内容类型分段",
        "document_structure": "按文档结构分段",
        "hierarchical": "父子结构分段",
        "custom_delimiter": "按指定符号分段",
        "question_based": "题目结构分段"
    }
    
    # 检查策略是否发生变化（但不清除预设状态，因为预设可能正在设置策略）
    previous_strategy = st.session_state.get('previous_chunking_strategy', None)
    if previous_strategy != chunking_strategy:
        # 只有当不是通过预设更改策略时，才清除预设状态
        if not st.session_state.get('applying_preset', False):
            if 'current_preset' in st.session_state:
                del st.session_state['current_preset']
        st.session_state['previous_chunking_strategy'] = chunking_strategy
    
    # 更新策略选择
    st.session_state['chunking_strategy'] = chunking_strategy
    st.session_state['chunking_config']['strategy'] = strategy_mapping.get(chunking_strategy, "固定长度分段")
    
    # 显示当前使用的策略
    st.info(f"🎯 当前策略: {strategy_mapping.get(chunking_strategy, '固定长度分段')}")
    
    # 根据选择的策略显示相应配置
    if chunking_strategy == "fixed_length":
        render_fixed_length_config()
    elif chunking_strategy == "content_type":
        render_content_type_config()
    elif chunking_strategy == "document_structure":
        render_document_structure_config()
    elif chunking_strategy == "hierarchical":
        render_hierarchical_config()
    elif chunking_strategy == "custom_delimiter":
        render_custom_delimiter_config()
    elif chunking_strategy == "question_based":
        render_question_based_config()
    
    # 自动保存配置
    save_current_config()

def render_fixed_length_config():
    """渲染固定长度切片配置"""
    
    st.markdown("**固定长度切片参数**")
    
    chunk_size = st.slider(
        "切片大小（字符数）",
        min_value=100,
        max_value=5000,
        value=st.session_state.get('chunk_size', 1000),
        step=100,
        help="每个切片的最大字符数"
    )
    
    overlap_size = st.slider(
        "重叠大小（字符数）",
        min_value=0,
        max_value=min(500, chunk_size // 2),
        value=st.session_state.get('overlap_size', 100),
        step=50,
        help="相邻切片之间的重叠字符数"
    )
    
    respect_boundaries = st.checkbox(
        "尊重边界",
        value=st.session_state.get('respect_boundaries', True),
        help="在句子或段落边界处切分，避免截断"
    )
    
    # 保存到chunking_config
    if 'chunking_config' not in st.session_state:
        st.session_state['chunking_config'] = {}
    st.session_state['chunking_config'].update({
        'chunk_size': chunk_size,
        'overlap_size': overlap_size,
        'respect_boundaries': respect_boundaries
    })

def render_content_type_config():
    """渲染按内容类型切片配置"""
    
    st.markdown("**内容类型切片参数**")
    
    content_types = st.multiselect(
        "要分离的内容类型",
        options=["headings", "paragraphs", "lists", "tables", "code_blocks", "quotes"],
        default=st.session_state.get('content_types', ["headings", "paragraphs"]),
        format_func=lambda x: {
            "headings": "标题",
            "paragraphs": "段落",
            "lists": "列表",
            "tables": "表格",
            "code_blocks": "代码块",
            "quotes": "引用"
        }[x]
    )
    
    merge_short_chunks = st.checkbox(
        "合并短切片",
        value=st.session_state.get('merge_short_chunks', True),
        help="将过短的切片与相邻切片合并"
    )
    
    min_chunk_size = st.slider(
        "最小切片大小",
        min_value=50,
        max_value=500,
        value=st.session_state.get('min_chunk_size', 100),
        help="切片的最小字符数"
    )
    
    # 保存到chunking_config
    if 'chunking_config' not in st.session_state:
        st.session_state['chunking_config'] = {}
    st.session_state['chunking_config'].update({
        'content_types': content_types,
        'merge_short_chunks': merge_short_chunks,
        'min_chunk_size': min_chunk_size
    })

def render_document_structure_config():
    """渲染按文档结构切片配置"""
    
    st.markdown("**文档结构切片参数**")
    
    structure_levels = st.multiselect(
        "结构级别",
        options=["chapter", "section", "subsection", "paragraph"],
        default=st.session_state.get('structure_levels', ["section"]),
        format_func=lambda x: {
            "chapter": "章节",
            "section": "小节",
            "subsection": "子节",
            "paragraph": "段落"
        }[x]
    )
    
    include_headers = st.checkbox(
        "包含标题",
        value=st.session_state.get('include_headers', True),
        help="在切片中包含对应的标题"
    )
    
    max_section_size = st.slider(
        "最大节大小",
        min_value=500,
        max_value=10000,
        value=st.session_state.get('max_section_size', 3000),
        help="单个节的最大字符数，超过则进一步切分"
    )
    
    # 保存到chunking_config
    if 'chunking_config' not in st.session_state:
        st.session_state['chunking_config'] = {}
    st.session_state['chunking_config'].update({
        'structure_levels': structure_levels,
        'include_headers': include_headers,
        'max_section_size': max_section_size
    })

def render_hierarchical_config():
    """渲染层级结构切片配置"""
    
    st.markdown("**层级结构切片参数**")
    
    max_depth = st.slider(
        "最大层级深度",
        min_value=1,
        max_value=6,
        value=st.session_state.get('max_depth', 3),
        help="处理的最大标题层级"
    )
    
    parent_context = st.checkbox(
        "包含父级上下文",
        value=st.session_state.get('parent_context', True),
        help="在子级切片中包含父级标题信息"
    )
    
    context_size = st.slider(
        "上下文大小",
        min_value=0,
        max_value=500,
        value=st.session_state.get('context_size', 100),
        help="包含的父级上下文字符数"
    )
    
    # 保存到chunking_config
    if 'chunking_config' not in st.session_state:
        st.session_state['chunking_config'] = {}
    st.session_state['chunking_config'].update({
        'max_depth': max_depth,
        'parent_context': parent_context,
        'context_size': context_size
    })

def render_custom_delimiter_config():
    """渲染自定义分隔符切片配置"""
    
    st.markdown("**自定义分隔符切片参数**")
    
    delimiters = st.text_area(
        "分隔符（每行一个）",
        value=st.session_state.get('delimiters', "\n\n\n\n---\n\n***"),
        help="用于切分文档的自定义分隔符"
    )
    
    delimiter_priority = st.selectbox(
        "分隔符优先级",
        options=["first_match", "longest_match", "shortest_match"],
        format_func=lambda x: {
            "first_match": "首次匹配",
            "longest_match": "最长匹配",
            "shortest_match": "最短匹配"
        }[x],
        index=0
    )
    
    keep_delimiter = st.checkbox(
        "保留分隔符",
        value=st.session_state.get('keep_delimiter', False),
        help="在切片中保留分隔符内容"
    )
    
    # 保存到chunking_config
    if 'chunking_config' not in st.session_state:
        st.session_state['chunking_config'] = {}
    st.session_state['chunking_config'].update({
        'delimiters': delimiters,
        'delimiter_priority': delimiter_priority,
        'keep_delimiter': keep_delimiter
    })

def render_question_based_config():
    """渲染题目结构切片配置"""
    
    st.markdown("**题目结构切片参数**")
    
    question_patterns = st.text_area(
        "题目模式（每行一个正则表达式）",
        value=st.session_state.get('question_patterns', "^\\d+[.、]\n^[一二三四五六七八九十]+[.、]\n^\\([一二三四五六七八九十]+\\)"),
        help="用于识别题目的正则表达式模式"
    )
    
    include_question_number = st.checkbox(
        "包含题目编号",
        value=st.session_state.get('include_question_number', True),
        help="在切片中保留题目编号"
    )
    
    merge_sub_questions = st.checkbox(
        "合并子题",
        value=st.session_state.get('merge_sub_questions', False),
        help="将子题与主题合并为一个切片"
    )
    
    max_question_size = st.slider(
        "最大题目大小",
        min_value=500,
        max_value=5000,
        value=st.session_state.get('max_question_size', 2000),
        help="单个题目的最大字符数，超过则进一步切分"
    )
    
    # 保存到chunking_config
    if 'chunking_config' not in st.session_state:
        st.session_state['chunking_config'] = {}
    st.session_state['chunking_config'].update({
        'question_patterns': question_patterns,
        'include_question_number': include_question_number,
        'merge_sub_questions': merge_sub_questions,
        'max_question_size': max_question_size
    })

def render_preset_configs():
    """渲染预设配置"""
    
    st.subheader("📋 预设配置")
    
    col1, col2, col3 = st.columns(3)
    
    with col1:
        if st.button("📚 学术论文", use_container_width=True):
            apply_academic_preset()
    
    with col2:
        if st.button("📖 技术文档", use_container_width=True):
            apply_technical_preset()
    
    with col3:
        if st.button("📝 通用文档", use_container_width=True):
            apply_general_preset()

def apply_academic_preset():
    """应用学术论文预设"""
    
    # 标记正在应用预设，防止策略变化时清除预设状态
    st.session_state['applying_preset'] = True
    
    # 清洗配置
    st.session_state.update({
        'clean_unicode': True,
        'remove_special_chars': True,
        'fix_line_breaks': True,
        'remove_headers_footers': True,
        'remove_duplicates': True,
        'remove_empty_lines': True,
        'min_line_length': 5,
        'preserve_formatting': False
    })
    
    # 切片配置 - 使用正确的英文键名
    st.session_state.update({
        'chunking_strategy': 'document_structure',
        'structure_levels': ['section', 'subsection'],
        'include_headers': True,
        'max_section_size': 2000,
        'max_depth': 3,
        'preserve_structure': True
    })
    
    # 设置预设状态标记
    st.session_state['current_preset'] = 'academic'
    
    # 清除应用预设标记
    st.session_state['applying_preset'] = False
    
    st.success("已应用学术论文预设配置")
    st.rerun()

def apply_technical_preset():
    """应用技术文档预设"""
    
    # 标记正在应用预设，防止策略变化时清除预设状态
    st.session_state['applying_preset'] = True
    
    # 清洗配置
    st.session_state.update({
        'clean_unicode': True,
        'remove_special_chars': False,
        'fix_line_breaks': True,
        'remove_headers_footers': False,
        'remove_duplicates': True,
        'remove_empty_lines': True,
        'min_line_length': 3,
        'preserve_formatting': True
    })
    
    # 切片配置 - 使用正确的英文键名
    st.session_state.update({
        'chunking_strategy': 'content_type',
        'content_types': ['headings', 'paragraphs', 'code_blocks', 'tables'],
        'merge_short_chunks': True,
        'min_chunk_size': 150
    })
    
    # 设置预设状态标记
    st.session_state['current_preset'] = 'technical'
    
    # 清除应用预设标记
    st.session_state['applying_preset'] = False
    
    st.success("已应用技术文档预设配置")
    st.rerun()

def apply_general_preset():
    """应用通用文档预设"""
    
    # 标记正在应用预设，防止策略变化时清除预设状态
    st.session_state['applying_preset'] = True
    
    # 清洗配置
    st.session_state.update({
        'clean_unicode': True,
        'remove_special_chars': True,
        'fix_line_breaks': True,
        'remove_headers_footers': False,
        'remove_duplicates': True,
        'remove_empty_lines': True,
        'min_line_length': 3,
        'preserve_formatting': False
    })
    
    # 切片配置 - 使用正确的英文键名
    st.session_state.update({
        'chunking_strategy': 'fixed_length',
        'chunk_size': 1000,
        'overlap_size': 100,
        'respect_boundaries': True
    })
    
    # 设置预设状态标记
    st.session_state['current_preset'] = 'general'
    
    # 清除应用预设标记
    st.session_state['applying_preset'] = False
    
    st.success("已应用通用文档预设配置")
    st.rerun()

def render_config_preview():
    """渲染配置预览"""
    
    st.subheader("👀 配置预览")
    
    # 显示当前预设状态
    current_preset = st.session_state.get('current_preset', None)
    if current_preset:
        preset_names = {
            'academic': '📚 学术论文',
            'technical': '📖 技术文档', 
            'general': '📝 通用文档'
        }
        st.info(f"当前使用预设: {preset_names.get(current_preset, current_preset)}")
    else:
        st.info("当前使用自定义配置")
    
    # 收集当前配置
    config = get_current_config()
    
    # 显示配置摘要
    col1, col2 = st.columns(2)
    
    with col1:
        st.markdown("**清洗配置摘要**")
        cleaning_summary = []
        if config.get('clean_unicode'):
            cleaning_summary.append("✅ Unicode规范化")
        if config.get('remove_special_chars'):
            cleaning_summary.append("✅ 移除特殊字符")
        if config.get('fix_line_breaks'):
            cleaning_summary.append("✅ 修复断行")
        if config.get('remove_duplicates'):
            cleaning_summary.append("✅ 去除重复")
        
        for item in cleaning_summary:
            st.markdown(item)
    
    with col2:
        st.markdown("**切片配置摘要**")
        strategy = config.get('chunking_strategy', 'fixed_length')
        strategy_names = {
            "fixed_length": "固定长度切片",
            "content_type": "按内容类型切片",
            "document_structure": "按文档结构切片",
            "hierarchical": "层级结构切片",
            "custom_delimiter": "自定义分隔符切片",
            "question_based": "题目结构切片"
        }
        
        st.markdown(f"**策略**: {strategy_names.get(strategy, strategy)}")
        
        if strategy == 'fixed_length':
            st.markdown(f"**切片大小**: {config.get('chunk_size', 1000)} 字符")
            st.markdown(f"**重叠大小**: {config.get('overlap_size', 100)} 字符")
        elif strategy == 'document_structure':
            st.markdown(f"**最大深度**: {config.get('max_depth', 3)}")
            st.markdown(f"**保留结构**: {'是' if config.get('preserve_structure', True) else '否'}")
        elif strategy == 'content_type':
            st.markdown(f"**最小切片大小**: {config.get('min_chunk_size', 150)} 字符")
            st.markdown(f"**合并短切片**: {'是' if config.get('merge_short_chunks', True) else '否'}")
    
    # 导出/导入配置
    st.markdown("---")
    col1, col2 = st.columns(2)
    
    with col1:
        if st.button("📤 导出配置", use_container_width=True):
            export_config(config)
    
    with col2:
        uploaded_config = st.file_uploader(
            "📥 导入配置",
            type=['json'],
            help="上传之前导出的配置文件"
        )
        
        if uploaded_config is not None:
            import_config(uploaded_config)

def get_current_config() -> Dict[str, Any]:
    """获取当前配置"""
    
    config = {}
    
    # 清洗配置
    cleaning_keys = [
        'clean_unicode', 'remove_special_chars', 'fix_line_breaks',
        'remove_headers_footers', 'remove_duplicates', 'remove_empty_lines',
        'min_line_length', 'preserve_formatting'
    ]
    
    for key in cleaning_keys:
        if key in st.session_state:
            config[key] = st.session_state[key]
    
    # 切片配置 - 从session_state直接获取
    chunking_keys = [
        'chunking_strategy', 'chunk_size', 'overlap_size', 'respect_boundaries',
        'content_types', 'merge_short_chunks', 'min_chunk_size',
        'structure_levels', 'include_headers', 'max_section_size',
        'max_depth', 'parent_context', 'context_size',
        'delimiters', 'delimiter_priority', 'keep_delimiter'
    ]
    
    for key in chunking_keys:
        if key in st.session_state:
            config[key] = st.session_state[key]
    
    # 从chunking_config中获取配置
    chunking_config = st.session_state.get('chunking_config', {})
    for key, value in chunking_config.items():
        config[key] = value
    
    print(f"[ConfigPage] 当前配置: {config}")
    return config

def export_config(config: Dict[str, Any]):
    """导出配置"""
    
    import json
    from datetime import datetime
    
    # 添加导出信息
    export_data = {
        'config': config,
        'export_time': datetime.now().isoformat(),
        'version': '1.0'
    }
    
    # 转换为JSON字符串
    config_json = json.dumps(export_data, indent=2, ensure_ascii=False)
    
    # 提供下载
    st.download_button(
        label="下载配置文件",
        data=config_json,
        file_name=f"processing_config_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json",
        mime="application/json"
    )

def import_config(uploaded_file):
    """导入配置"""
    
    try:
        import json
        
        # 读取文件内容
        config_data = json.load(uploaded_file)
        
        # 提取配置
        if 'config' in config_data:
            imported_config = config_data['config']
        else:
            imported_config = config_data
        
        # 更新session state
        for key, value in imported_config.items():
            st.session_state[key] = value
        
        # 保存到文件
        config_manager.save_config(imported_config)
        
        st.success("配置导入成功！")
        st.rerun()
        
    except Exception as e:
        st.error(f"配置导入失败: {str(e)}")

def initialize_config_from_file():
    """从文件初始化配置到session_state"""
    
    # 检查是否需要从文件加载配置
    if not st.session_state.get('config_initialized', False):
        saved_config = config_manager.load_config()
        
        # 更新session_state
        for key, value in saved_config.items():
            if key not in st.session_state:
                st.session_state[key] = value
        
        # 标记已初始化
        st.session_state['config_initialized'] = True
        print("[ConfigPage] 配置已从文件初始化")

def render_config_actions():
    """渲染配置操作按钮"""
    
    st.subheader("💾 配置管理")
    
    col1, col2, col3 = st.columns(3)
    
    with col1:
        if st.button("💾 保存配置", use_container_width=True):
            if save_current_config():
                st.success("配置已保存！")
            else:
                st.error("配置保存失败")
    
    with col2:
        if st.button("🔄 重新加载", use_container_width=True):
            load_config_from_file()
            st.success("配置已重新加载！")
            st.rerun()
    
    with col3:
        if st.button("🔧 重置默认", use_container_width=True):
            if config_manager.reset_config():
                load_config_from_file()
                st.success("已重置为默认配置！")
                st.rerun()
            else:
                st.error("重置配置失败")

def save_current_config() -> bool:
    """保存当前配置到文件"""
    
    try:
        config = get_current_config()
        return config_manager.save_config(config)
    except Exception as e:
        print(f"[ConfigPage] 保存配置失败: {str(e)}")
        return False

def load_config_from_file():
    """从文件加载配置到session_state"""
    
    saved_config = config_manager.load_config()
    
    # 更新session_state
    for key, value in saved_config.items():
        st.session_state[key] = value
    
    # 重置初始化标记，确保下次能正确加载
    st.session_state['config_initialized'] = True